package com.zpark.harmonyos_gmd_17.utils;

import ohos.app.Context;
import ohos.net.NetHandle;
import ohos.net.NetManager;
import ohos.net.NetStatusCallback;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;

/**
 * http请求工具类
 */
public class HttpRequestUtil {

    /**
     * 发送 Http请求获取数据
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param method 请求方式
     * @param token 访问受限资源携带token，⾮受限资源传递null即可
     * @param data 请求参数
     * @return 响应数据
     */
    private static String sendHttpRequest(Context context, String urlStr, String method, String token, String data){
        String result = null;
        /*
               网络管理开发步骤
                1）调用NetManager.getInstance(Context)获取网络管理的实例对象。
                2）调用NetManager.getDefaultNet()获取默认的数据网络。
                3）调用NetHandle.openConnection()打开一个URL。
                4）通过URL链接实例访问网站。
             */
        // 调用NetManager.getInstance(Context)获取网络管理的实例对象。
        NetManager netManager = NetManager.getInstance(context);

        // 查询当前是否有默认可用的数据网络。
        if (!netManager.hasDefaultNet()) {
            // 没有可用网络
            return null;
        }

        // 获取当前默认的数据网络句柄(返回nethhandle对象)
        NetHandle netHandle = netManager.getDefaultNet();

        // 可以获取网络状态的变化
        NetStatusCallback callback = new NetStatusCallback(){
            // 重写需要获取的网络状态变化的override函数
        };

        // 获取当前默认的数据网络状态变化。
            /*
                接收默认数据网络的状态更改通知。
                removeNetStatusCallback(ohos.net.NetStatusCallback)可以用来取消接收状态变化通知。
                此方法需要ohos.permission。GET_NETWORK_INFO许可。
                参数说明:
                    callback -回叫，通知应用程序网络状态发生变化。具体请参见NetStatusCallback。
                返回:
                    如果收到通知则返回true;否则返回false。
             */
        boolean sign = netManager.addDefaultNetStatusCallback(callback);

        // 通过openConnection来获取URLConnection
        HttpURLConnection connection = null;

        try{

                /*
                    从字符串表示创建URL对象。
                    这个构造函数相当于调用第一个参数为空的双参数构造函数。
                    参数:
                        spec -要解析为URL的字符串。
                    抛出:
                        malformmedurlexception -如果没有指定协议，或发现未知协议，或spec为空。
                 */
            URL url = new URL(urlStr);

                /*
                    使用指定的代理访问URL。
                    参数说明:
                        url - url连接。
                        proxy -代理。
                    返回:
                        返回与给定url匹配的urlconnection对象。
                    抛出:
                        IOException -如果在打开连接时发生错误。
                 */
            connection = (HttpURLConnection) netHandle.openConnection(url, Proxy.NO_PROXY);

            // 设置请求方式
            connection.setRequestMethod(method);

            // 如果通过请求体传递参数到服务端接⼝，需要对connection进⾏额外的设置
            if (data != null) {
                // 需要将数据封装到请求体
                // 允许通过此⽹络连接向服务端写数据
                connection.setDoOutput(true);
                // 将数据以json格式进行传递
                connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            }

            // 如果参数token！=null,则需要将token设置到请求头
            if (token != null) {
                // 设置token信息
                connection.setRequestProperty("token", token);
            }

            /*
                打开到此URL引用的资源的通信链接(如果尚未建立这样的连接)。
                如果在连接已经打开时调用connect方法(由值为true的connected字段表示)，则忽略该调用。
             */
            connection.connect();

            // 向服务端传递data中的数据
            if (data != null) {
                // 将请求参数转为字节
                byte[] bytes = data.getBytes("UTF-8");
                // 获取输出流对象
                OutputStream outputStream = connection.getOutputStream();
                // 写出数据
                outputStream.write(bytes);
                outputStream.flush();
            }

            // 之后可进行url的其他操作
            // 从连接中获取输入流，读取api接口返回数据
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                // 读取响应数据
                InputStream inputStream = connection.getInputStream();
                // 创建StringBuilder
                StringBuilder builder = new StringBuilder();
                byte[] bytes = new byte[1024];
                int len = -1;
                // 循环读取数据
                while ((len = inputStream.read(bytes)) != -1) {
                    // 将字节转为字符串
                    builder.append(new String(bytes, 0, len));
                }

                result = builder.toString();
                System.out.println(result);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 断开网络连接
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }

    /**
     * 发送 Http GET请求获取数据
     * @param context 应用上下文
     * @param urlStr 请求url
     * @return 响应数据
     */
    public static String sendGetHttpRequest(Context context, String urlStr){
        return sendHttpRequest(context, urlStr, "GET", null, null);
    }

    /**
     * 发送 Http GET请求获取数据(携带token)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param token 访问受限资源携带token，⾮受限资源传递null即可
     * @return 响应数据
     */
    public static String sendGetHttpRequestWithToken(Context context, String urlStr, String token){
        return sendHttpRequest(context, urlStr, "GET", token, null);
    }

    /**
     * 发送 Http POST请求获取数据(不携带参数、不携带token)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @return 响应数据
     */
    public static String sendPostHttpRequest(Context context, String urlStr){
        return sendHttpRequest(context, urlStr, "POST", null, null);
    }

    /**
     * 发送 Http POST请求获取数据(携带参数)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param data 请求参数
     * @return 响应数据
     */
    public static String sendPostHttpRequestWithData(Context context, String urlStr, String data){
        return sendHttpRequest(context, urlStr, "POST", null, data);
    }

    /**
     * 发送 Http POST请求获取数据(携带Token)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param token 请求参数
     * @return 响应数据
     */
    public static String sendPostHttpRequestWithToken(Context context, String urlStr, String token){
        return sendHttpRequest(context, urlStr, "POST", token, null);
    }

    /**
     * 发送 Http POST请求获取数据(携带token、携带参数)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param token 访问受限资源携带token，⾮受限资源传递null即可
     * @param data 请求参数
     * @return 响应数据
     */
    public static String sendPostHttpRequestWithTokenData(Context context, String urlStr, String token, String data){
        return sendHttpRequest(context, urlStr, "POST", token, data);
    }

    /**
     * 发送 Http DELETE请求获取数据(携带token、携带参数)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param token 访问受限资源携带token，⾮受限资源传递null即可
     * @param data 请求参数
     * @return 响应数据
     */
    public static String sendDeleteHttpRequestWithTokenData(Context context, String urlStr, String token, String data){
        return sendHttpRequest(context, urlStr, "DELETE", token, data);
    }

    /**
     * 发送 Http UPDATE请求获取数据(携带token、携带参数)
     * @param context 应用上下文
     * @param urlStr 请求url
     * @param token 访问受限资源携带token，⾮受限资源传递null即可
     * @param data 请求参数
     * @return 响应数据
     */
    public static String sendUpdateHttpRequestWithTokenData(Context context, String urlStr, String token, String data){
        return sendHttpRequest(context, urlStr, "UPDATE", token, data);
    }


}
